package com.bjb.vr.common.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.annotation.InvalidateCache;
import com.bjb.vr.common.ao.ClientRequestAo;
import com.bjb.vr.common.ao.ResDictionaryAo;
import com.bjb.vr.common.constant.CacheConstant;
import com.bjb.vr.common.constant.Constants;
import com.bjb.vr.common.constant.ResDicType;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.dto.ResDictionary;
import com.bjb.vr.common.mapper.ResDictionaryMapper;
import com.bjb.vr.common.utils.GuavaCacheUtil;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.ResDictionaryVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;

/**
 * @author admin
 * @description 针对表【res_dictionary】的数据库操作Service实现
 * @createDate 2022-03-23 14:44:42
 */
@Service
public class ResDictionaryService extends ServiceImpl<ResDictionaryMapper, ResDictionary> {

    private static final String PRIMARY_CODE = "1008";
    private static final String UNION = "01";
    private static final String PRIMARY_TYPE = "0";
    private static final String JUNIOR_TYPE = "1";

    @Autowired
    private ResDictionaryMapper dictionaryMapper;

    /**
     * 根据字典编码查询
     *
     * @param name
     * @return
     */
    public List<ResDictionary> getResDictionaryByName(String name) {
        try {
            return GuavaCacheUtil.getDictionaryCache().get(CacheConstant.DICNAME + name);
        } catch (ExecutionException e) {
            log.error(">>> 查询缓存失败, 将查询数据库 >>>");
            LambdaQueryWrapper<ResDictionary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StringUtils.isNotBlank(name), ResDictionary::getDictName, name);
            return dictionaryMapper.selectList(queryWrapper);
        }
    }

    /**
     * 根据字典编码查询
     *
     * @param code
     * @return
     */
    public ResDictionary getResDictionaryByCode(String code) {
        try {
            return GuavaCacheUtil.getDictionaryCacheOne().get(CacheConstant.DICCODE + code);
        } catch (Exception e) {
            log.error(">>> 查询缓存失败, 将查询数据库 >>>");
            LambdaQueryWrapper<ResDictionary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StringUtils.isNotBlank(code), ResDictionary::getDictCode, code);
            return dictionaryMapper.selectOne(queryWrapper);
        }
    }

    /**
     * 根据字典名称查询
     *
     * @param name
     * @return
     */
    public ResDictionary getDictionaryByName(String name) {
        try {
            return GuavaCacheUtil.getDictionaryCacheOne().get(CacheConstant.DICNAME + name);
        } catch (Exception e) {
            log.error(">>> 查询缓存失败, 将查询数据库 >>>");
            LambdaQueryWrapper<ResDictionary> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StringUtils.isNotBlank(name), ResDictionary::getDictName, name);
            return dictionaryMapper.selectOne(queryWrapper);
        }
    }

    /**
     * 根据字典类型查询
     *
     * @param type
     * @return
     */
    public List<ResDictionaryVo> getResDictionaryList(String type) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        try {
            // 先查询缓存
            List<ResDictionary> dictionaries = GuavaCacheUtil.getDictionaryCache().get(type);
            List<ResDictionaryVo> resDictionaryVoList = convertPoToVo(dictionaries);
            return resDictionaryVoList;
        } catch (Exception e) {
            log.error(">>> 查询缓存失败, 将查询数据库 >>>");
            // 查询数据库
            LambdaQueryWrapper<ResDictionary> queryWrapper = Wrappers.lambdaQuery(ResDictionary.class);
            queryWrapper.eq(ResDictionary::getDictStatus, Constants.ENABLE);
            queryWrapper.eq(ResDictionary::getDictType, type);
            List<ResDictionary> dictionaryList = this.list(queryWrapper);
            List<ResDictionaryVo> resDictionaryVoList = convertPoToVo(dictionaryList);
            return resDictionaryVoList;
        } finally {
            ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        }
    }

    /**
     * 根据字典类型查询
     *
     * @param type
     * @return
     */
    public List<ResDictionaryVo> getResDictionaryList(String type, ClientRequestAo clientRequestAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        try {
            // 查询数据库
            LambdaQueryWrapper<ResDictionary> queryWrapper = Wrappers.lambdaQuery(ResDictionary.class);
            queryWrapper.eq(ResDictionary::getDictType, type);
            if (ResDicType.SUBJECT.getType().equals(type)) {
                queryWrapper.eq(!StringUtils.isEmpty(clientRequestAo.getThemeCode()), ResDictionary::getThemeCode, clientRequestAo.getThemeCode());
            }
            List<ResDictionary> dictionaryList = this.list(queryWrapper);
            List<ResDictionaryVo> resDictionaryVoList = convertPoToVo(dictionaryList);
            return resDictionaryVoList;
        } catch (Exception e) {
            log.error(">>> 查询缓存失败, 将查询数据库 >>>");
            return null;
        } finally {
            ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        }
    }

    /**
     * 联动查询
     *
     * @param resDictionaryAo
     * @return
     */
    public List<ResDictionaryVo> queryDictionaryByPeriodLink(ResDictionaryAo resDictionaryAo) {
        // 如果不传code，那就只查对应的type类型
        if (StringUtils.isBlank(resDictionaryAo.getDictCode())) {
            // 如果type为01，则查询type为0和1的并集
            if (UNION.equals(resDictionaryAo.getDictType())) {
                List<ResDictionaryVo> dictionaryList = dictionaryMapper.queryUnionData();
                return dictionaryList;
            } else {
                List<ResDictionaryVo> resDictionaryList = getResDictionaryList(resDictionaryAo.getDictType());
                return resDictionaryList;
            }
        } else {
            // 如果传1008，则查询小学阶段的学科，否则查询中学阶段的学科
            if (PRIMARY_CODE.equals(resDictionaryAo.getDictCode())) {
                List<ResDictionaryVo> resDictionaryList = getResDictionaryList(PRIMARY_TYPE);
                return resDictionaryList;
            } else {
                List<ResDictionaryVo> resDictionaryList = getResDictionaryList(JUNIOR_TYPE);
                return resDictionaryList;
            }
        }
    }

    /**
     * 数据类型转换
     *
     * @param dictionaryList
     * @return
     */
    private List<ResDictionaryVo> convertPoToVo(List<ResDictionary> dictionaryList) {
        List<ResDictionaryVo> resDictionaryVos = new ArrayList<>();
        dictionaryList.stream().forEach(resDictionary -> {
            ResDictionaryVo resDictionaryVo = new ResDictionaryVo();
            BeanUtils.copyProperties(resDictionary, resDictionaryVo);
            resDictionaryVos.add(resDictionaryVo);
        });
        return resDictionaryVos;
    }

    /**
     * 添加字典
     *
     * @param resDictionaryAo
     * @return
     */
    @InvalidateCache(cacheName = CacheConstant.DICTIONARY)
    public boolean addDictionary(ResDictionaryAo resDictionaryAo) {
        ResDictionary resDictionary = new ResDictionary();
        BeanUtils.copyProperties(resDictionaryAo, resDictionary);
        return save(resDictionary);
    }

    /**
     * 更新字典
     *
     * @param resDictionaryAo
     * @return
     */
    @InvalidateCache(cacheName = CacheConstant.DICTIONARY)
    public boolean updateDictionary(ResDictionaryAo resDictionaryAo) {
        ResDictionary resDictionary = new ResDictionary();
        BeanUtils.copyProperties(resDictionaryAo, resDictionary);
        return updateById(resDictionary);
    }

    /**
     * 查询字典
     *
     * @param resDictionaryAo
     * @return
     */
    public IPage<ResDictionaryVo> queryDictionary(ResDictionaryAo resDictionaryAo) {
        // 分页条件
        Page<ResDictionary> resDictionary = new Page<>(resDictionaryAo.getCurrent(), resDictionaryAo.getSize());
        LambdaQueryWrapper<ResDictionary> queryWrapper = Wrappers.lambdaQuery(ResDictionary.class);
        // 查询条件
        queryWrapper.in(Objects.nonNull(resDictionaryAo.getId()), ResDictionary::getId, resDictionaryAo.getId());
        queryWrapper.eq(Objects.nonNull(resDictionaryAo.getDictCode()), ResDictionary::getDictCode, resDictionaryAo.getDictCode());
        queryWrapper.eq(Objects.nonNull(resDictionaryAo.getDictType()), ResDictionary::getDictType, resDictionaryAo.getDictType());
        queryWrapper.eq(Objects.nonNull(resDictionaryAo.getDictStatus()), ResDictionary::getDictStatus, resDictionaryAo.getDictStatus());
        queryWrapper.like(StringUtils.isNotBlank(resDictionaryAo.getDictName()), ResDictionary::getDictName, resDictionaryAo.getDictName());
        // 执行查询
        Page<ResDictionary> dictionaryPage = this.page(resDictionary, queryWrapper);
        List<ResDictionaryVo> resDictionaryVos = convertPoToVo(dictionaryPage.getRecords());
        IPage<ResDictionaryVo> voIPage = new Page<ResDictionaryVo>(dictionaryPage.getCurrent(), dictionaryPage.getSize(), dictionaryPage.getTotal());
        voIPage.setRecords(resDictionaryVos);
        return voIPage;
    }

    /**
     * 获取平台名称
     *
     * @param themeCodes
     * @return
     */
    public String getPlatformName(String[] themeCodes) {
        List<String> dicts = dictionaryMapper.getPlatformName(themeCodes);
        StringBuilder sb = new StringBuilder();
        dicts.stream().forEach(dict -> sb.append(dict).append(","));
        sb.deleteCharAt(sb.lastIndexOf(","));
        return sb.toString().trim();
    }

    /**
     * 查询字典--根据code--层级关系
     *
     * @param resDictionaryAo
     * @return
     */
    public List<ResDictionaryVo> queryDictListByCode(ResDictionaryAo resDictionaryAo) {
        // 查询部分数据
        ResDictionaryVo dictData = dictionaryMapper.selectOneByCode(resDictionaryAo.getDictCode());
        // 查询全部数据
        List<ResDictionaryVo> voList = dictionaryMapper.selectListAll();
        // 封装数据
        List<ResDictionaryVo> dictDataList = new ArrayList<>();
        Long parentId = dictData.getId();
        List<ResDictionaryVo> resDictionaries = queryDictList(voList, parentId);
        dictData.setChildrens(resDictionaries);
        dictDataList.add(dictData);
        return dictDataList;
    }

    /**
     * 查询字典--根据type--层级关系
     *
     * @param resDictionaryAo
     * @return
     */
    public List<ResDictionaryVo> queryDictListByType(ResDictionaryAo resDictionaryAo) {
        // 查询部分数据
        List<ResDictionaryVo> subVoList = dictionaryMapper.selectListByType(resDictionaryAo.getDictType());
        // 查询全部数据
        List<ResDictionaryVo> voList = dictionaryMapper.selectListAll();
        // 封装数据
        List<ResDictionaryVo> dictDataList = new ArrayList<>();
        for (ResDictionaryVo dictData : subVoList) {
            Long parentId = dictData.getId();
            List<ResDictionaryVo> resDictionaries = queryDictList(voList, parentId);
            dictData.setChildrens(resDictionaries);
            dictDataList.add(dictData);
        }
        return dictDataList;
    }

    /**
     * 递归查询数据
     *
     * @return
     */
    private List<ResDictionaryVo> queryDictList(List<ResDictionaryVo> voList, Long parentId) {
        List<ResDictionaryVo> result = new ArrayList<>();
        for (ResDictionaryVo voObj : voList) {
            if (voObj.getParentId().equals(parentId)) {
                List<ResDictionaryVo> subMenus = queryDictList(voList, voObj.getId());
                voObj.setChildrens(subMenus);
                result.add(voObj);
            }
        }
        return result;
    }

}




